package com.nineclock.system.service.impl;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;


import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.nineclock.common.constant.NcConstant;
import com.nineclock.common.constant.SMSConstant;
import com.nineclock.common.enums.MessageTypeEnum;
import com.nineclock.common.enums.ResponseEnum;
import com.nineclock.common.exception.NcException;
import com.nineclock.common.filter.CurrentUserHolder;
import com.nineclock.common.oss.OssClientUtils;
import com.nineclock.common.utils.BeanHelper;
import com.nineclock.system.dto.*;
import com.nineclock.system.im.HxImManager;
import com.nineclock.system.mapper.*;
import com.nineclock.system.message.MessageDTO;
import com.nineclock.system.pojo.*;
import com.nineclock.system.service.SysCompanyService;
import com.nineclock.system.service.SysCompanyUserService;
import com.nineclock.system.service.SysUserService;
import net.bytebuddy.asm.Advice;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.util.Date;
import java.util.List;

@Service
@Transactional
public class SysCompanyServiceImpl implements SysCompanyService {

    @Autowired
    private SysCompanyMapper companyMapper;

    @Autowired
    private OssClientUtils ossClientUtils;

    @Autowired
    private SysCompanyUserMapper companyUserMapper;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private SysCompanyUserRoleMapper companyUserRoleMapper;

    @Autowired
    private SysCompanyUserService companyUserService;

    @Autowired
    private SysRoleMapper roleMapper;

    @Autowired
    private SysUserMapper userMapper;

    @Autowired
    private SysUserService userService;

    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    @Autowired
    private HxImManager imManager;


    @Override
    public List<SysCompanyDTO> queryUserJoinCompany(Long userId) {
        List<SysCompany> companyList = companyMapper.queryUserJoinCompany(userId);

        if (CollectionUtils.isEmpty(companyList)) {
            throw new NcException(ResponseEnum.USER_NOT_JOIN_COMPANY);
        }

        return BeanHelper.copyWithCollection(companyList, SysCompanyDTO.class);
    }

    @Override
    public SysCompanyDTO queryCompanyInfo() {

        // 从线程本地变量中获取当前登录用户信息
        Long companyId = CurrentUserHolder.get().getCompanyId();

        // 根据企业id查询企业信息
        SysCompany sysCompany = companyMapper.selectById(companyId);

        // 数据转换
        SysCompanyDTO companyDTO = BeanHelper.copyProperties(sysCompany, SysCompanyDTO.class);

        return companyDTO;
    }

    @Override
    public String uploadOSS(MultipartFile file) throws Exception {
        // 1.参数校验
        // 1.1 参数是否为空
        if (file == null) {
            throw new NcException(ResponseEnum.INVALID_PARAM_ERROR);
        }

        // 1.2 校验文件类型
        String contentType = file.getContentType();
        if (!NcConstant.ALLOWED_IMG_TYPES.contains(contentType)) {
            throw new NcException(ResponseEnum.INVALID_FILE_TYPE);
        }

        // 1.3 校验文件大小
        long fileSize = file.getSize();
        if (fileSize > NcConstant.maxFileSize) {
            throw new NcException(ResponseEnum.FILE_SIZE_EXCEED_MAX_LIMIT);
        }

        // 2.调用阿里云oss上传文件
        String url = ossClientUtils.uploadFile(file.getOriginalFilename(), file.getInputStream());

        return url;
    }

    @Override
    public void updateCompanyInfo(SysCompanyDTO companyDTO) {
        // 1.获取线程本地变量中的当前登录用户信息
        Long companyId = CurrentUserHolder.get().getCompanyId();

        // 2.更新企业信息表
        SysCompany company = new SysCompany();
        company.setId(companyId);
        company.setName(companyDTO.getName());
        company.setLogo(companyDTO.getLogo());
        companyMapper.updateById(company);

        // 3.更新员工信息表
        LambdaQueryWrapper<SysCompanyUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysCompanyUser::getCompanyId, companyId);

        SysCompanyUser sysCompanyUser = new SysCompanyUser();
        sysCompanyUser.setCompanyName(companyDTO.getName());
        companyUserMapper.update(sysCompanyUser, wrapper);

    }

    @Override
    public void changeSysAdmin(String code, Long userId) {
        // 参数校验
        if (StringUtils.isEmpty(code) || userId == null) {
            throw new NcException(ResponseEnum.INVALID_PARAM_ERROR);
        }

        // 根据员工id查询员工信息，得到手机号码
        SysCompanyUser companyUser = companyUserMapper.selectById(userId);

        // 校验验证码是否正确
        String key = SMSConstant.SMS_CHANGE_MANAGER_KEY_PREFIX + companyUser.getMobile();
        String redisCode = (String) redisTemplate.opsForValue().get(key);

        if (StringUtils.isEmpty(redisCode) || !redisCode.equals(code)) {
            // 当redis验证码为空，或 验证码不一致
            throw new NcException(ResponseEnum.INVALID_VERIFY_CODE);
        }

        // 查询原本的主管理员信息
        SysCompanyUserDTO currentAdmin = companyUserService.getCurrentAdmin();

        // 查询当前公司的主管理员角色id
        LambdaQueryWrapper<SysRole> roleWrapper = new LambdaQueryWrapper<>();
        roleWrapper.eq(SysRole::getCompanyId, CurrentUserHolder.get().getCompanyId());
        roleWrapper.eq(SysRole::getRoleName, NcConstant.ADMIN_ROLE_SYS);
        SysRole role = roleMapper.selectOne(roleWrapper);

        // 更新员工角色关系表中的员工id
        LambdaQueryWrapper<SysCompanyUserRole> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysCompanyUserRole::getCompanyUserId, currentAdmin.getId());
        wrapper.eq(SysCompanyUserRole::getRoleId, role.getId());

        SysCompanyUserRole companyUserRole = new SysCompanyUserRole();
        companyUserRole.setCompanyUserId(userId);
        companyUserRoleMapper.update(companyUserRole, wrapper);

    }

    @Override
    public List<SysCompanyDTO> queryCompanyByName(String keyword) {
        // 参数校验
        if (StringUtils.isEmpty(keyword)) {
            throw new NcException(ResponseEnum.INVALID_PARAM_ERROR);
        }

        LambdaQueryWrapper<SysCompany> wrapper = new LambdaQueryWrapper<>();
        wrapper.like(SysCompany::getName, keyword);
        List<SysCompany> sysCompanyList = companyMapper.selectList(wrapper);

        if (!CollectionUtils.isEmpty(sysCompanyList)) {
            return BeanHelper.copyWithCollection(sysCompanyList, SysCompanyDTO.class);
        }
        return null;
    }

    @Override
    public void applyJoinCompany(SysApplyJoinCompanyUserDTO applyJoinCompanyUserDTO) {
        // 参数校验
        if (applyJoinCompanyUserDTO == null) {
            throw new NcException(ResponseEnum.INVALID_PARAM_ERROR);
        }

        // 更新用户表，用户id前端没有传
        SysUserDTO userDTO = userService.queryUser(applyJoinCompanyUserDTO.getMobile());

        SysUser sysUser = new SysUser();
        sysUser.setId(userDTO.getId());
        sysUser.setUsername(applyJoinCompanyUserDTO.getUserName());
        sysUser.setEmail(applyJoinCompanyUserDTO.getEmail());
        sysUser.setUpdateTime(new Date());
        sysUser.setLastLoginCompanyId(applyJoinCompanyUserDTO.getCompanyId());
        userMapper.updateById(sysUser);


        // 插入员工表，员工数据
        SysCompanyUser sysCompanyUser = new SysCompanyUser();
        sysCompanyUser.setUserId(userDTO.getId());
        sysCompanyUser.setCompanyId(applyJoinCompanyUserDTO.getCompanyId());
        sysCompanyUser.setCompanyName(applyJoinCompanyUserDTO.getCompanyName());
        sysCompanyUser.setPost(applyJoinCompanyUserDTO.getPost());
        sysCompanyUser.setEmail(applyJoinCompanyUserDTO.getEmail());
        sysCompanyUser.setTimeEntry(new Date());
        sysCompanyUser.setRemark(applyJoinCompanyUserDTO.getApplyReason());
        sysCompanyUser.setEnable((short) 0);
        sysCompanyUser.setCreateTime(new Date());
        sysCompanyUser.setUpdateTime(new Date());
        sysCompanyUser.setMobile(applyJoinCompanyUserDTO.getMobile());
        sysCompanyUser.setUserName(applyJoinCompanyUserDTO.getUserName());
        sysCompanyUser.setImageUrl(applyJoinCompanyUserDTO.getImageUrl());

        companyUserMapper.insert(sysCompanyUser);


        // 发送消息至MQ
        // 创建消息内容
        MessageDTO messageDTO = new MessageDTO();
        messageDTO.setMessageType(MessageTypeEnum.COMPANY_APPLY.getType()); // 消息类型（申请加入企业）
        messageDTO.setCompanyId(applyJoinCompanyUserDTO.getCompanyId().toString());
        messageDTO.setTitle(MessageTypeEnum.COMPANY_APPLY.getTitle());
        messageDTO.setContent(sysCompanyUser.getUserName() + " 申请加入企业，请及时审批"); // 内容
        messageDTO.setUseStatus(0); // 是否已读，0代表未读
        messageDTO.setAudience(MessageTypeEnum.COMPANY_APPLY.getAudience());

        // 查询企业的主管理员信息
        SysCompanyUser mainAdmin = companyUserMapper.queryMainAdminCompanyUser(
                applyJoinCompanyUserDTO.getCompanyId());

        messageDTO.setTargets(Lists.newArrayList(mainAdmin.getMobile())); // 发送的目标用户手机号码
        messageDTO.setApproveStatue(0); // 未审核
        messageDTO.setApplyUserId(userDTO.getId()); // 申请人用户id
        messageDTO.setApplyUsername(sysUser.getUsername()); // 申请人用户名
        messageDTO.setApproveUserId(mainAdmin.getUserId()); // 审批人用户id
        messageDTO.setApproveUsername(mainAdmin.getUserName()); // 审批人用户名


        // 参数1-主题:标签，参数2-消息内容
        rocketMQTemplate.convertAndSend("messagePushTopic", JSON.toJSONString(messageDTO));

        // 将用户注册到环信
        imManager.registerUser2HuanXing(sysUser);
    }

    @Override
    public void allowedJoinCompany(SysAllowedJoinCompanyUserDTO allowedJoinCompanyUserDTO) {
        if (allowedJoinCompanyUserDTO.getApproved()) { // 审核通过
            // 修改员工状态为有效
            LambdaQueryWrapper<SysCompanyUser> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(SysCompanyUser::getUserId, allowedJoinCompanyUserDTO.getApplyUserId());
            wrapper.eq(SysCompanyUser::getCompanyId, CurrentUserHolder.get().getCompanyId());
            SysCompanyUser companyUser = companyUserMapper.selectOne(wrapper);
            companyUser.setEnable((short) 1);
            companyUser.setUpdateTime(new Date());

            companyUserMapper.updateById(companyUser);

            // 推送消息至MQ，给申请用户推送通知
            MessageDTO messageDTO = new MessageDTO();
            messageDTO.setMessageType(MessageTypeEnum.COMPANY_APPLY_PASS.getType());
            messageDTO.setCompanyId(CurrentUserHolder.get().getCompanyId().toString());
            messageDTO.setTitle(MessageTypeEnum.COMPANY_APPLY_PASS.getTitle());
            messageDTO.setContent(companyUser.getUserName() + " 申请加入企业，已通过");
            messageDTO.setUseStatus(0); // 发给申请用户的，他此时未读
            messageDTO.setAudience(MessageTypeEnum.COMPANY_APPLY_PASS.getAudience());
            messageDTO.setTargets(Lists.newArrayList(companyUser.getMobile())); // 目标用户的手机号码
            messageDTO.setApproveStatue(1); // 已审核
            messageDTO.setApproveResult("1"); // 审核通过
            messageDTO.setApplyUserId(companyUser.getUserId()); // 申请人用户id
            messageDTO.setApplyUsername(companyUser.getUserName()); // 申请人用户名
            messageDTO.setApproveUserId(CurrentUserHolder.get().getId()); // 审批人用户id
            messageDTO.setApproveUsername(CurrentUserHolder.get().getUsername()); // 审批人用户名
            rocketMQTemplate.convertAndSend("messagePushTopic", JSON.toJSONString(messageDTO));

            // 推送消息至MQ，修改原本通知记录的状态
            rocketMQTemplate.convertAndSend("allowedJoinCompanyTopic", allowedJoinCompanyUserDTO.getNotifyMsgId());


        } else {
            // 删除员工信息
            LambdaQueryWrapper<SysCompanyUser> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(SysCompanyUser::getUserId, allowedJoinCompanyUserDTO.getApplyUserId());
            wrapper.eq(SysCompanyUser::getCompanyId, CurrentUserHolder.get().getCompanyId());
            companyUserMapper.delete(wrapper);
        }
    }
}
